package com.wyt.common.sqljdbc;

import com.alibaba.druid.pool.DruidDataSourceFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.function.Consumer;

/**
 * 通用数据源管理工具类
 */
public class DruidDataSourceUtils {

    private static final Logger logger = LoggerFactory.getLogger(DruidDataSourceUtils.class);

    private static Map<String, DataSource> dataSourceMap = new HashMap<>();

    /**
     * 根据唯一标识构建数据源
     */
    private static DataSource buildDataSource(String uid) {
        if (!dataSourceMap.containsKey(uid)) {
            // @TODO 根据唯一标识获取创建数据源的基础信息
            String ip = "";
            Integer port = 0;
            String dbName = "";
            String username = "";
            String password = "";
            String driver = "";

            Properties properties = new Properties();
            properties.put("url", buildUrl(ip, port, dbName));
            properties.put("username", username);
            properties.put("password", password);
            properties.put("driverClassName", driver);
            //开启监控功能
            properties.put("filters", "stat");
            //配置初始化大小、最小、最大
            properties.put("initialSize", "3");
            properties.put("minIdle", "3");
            properties.put("maxActive", "3");
            //配置获取连接等待超时的时间
            properties.put("maxWait", "60000");
            //配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
            properties.put("timeBetweenEvictionRunsMillis", "60000");
            //配置一个连接在池中最小生存时间，单位是毫秒
            properties.put("minEvictableIdleTimeMillis", "30000");

            properties.put("validationQuery", "SELECT 1 FROM DUAL");
            properties.put("testWhileIdle", "true");
            properties.put("testOnBorrow", "true");
            properties.put("testOnReturn", "false");
            try {
                DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
                dataSourceMap.put(uid, dataSource);
            } catch (Exception e) {
                throw new RuntimeException("创建数据源失败", e);
            }

            logger.info("初始化数据库连接池结束");
        }
        return dataSourceMap.get(uid);
    }
    /**
     * 根据唯一标识获取连接
     */
    private static Connection getConnection(String uid) throws Exception {
        DataSource dataSource = buildDataSource(uid);
        Connection connection = dataSource.getConnection();
        return connection;
    }

    /**
     * 执行需要返回结果的sql
     */
    public static void execute(String uid, String sql, Consumer<ResultSet> consumer){
        logger.info("开始执行sql=[{}]",sql);
        try (Connection connection = getConnection(uid);
             Statement statement = connection.createStatement();
             ResultSet resultSet = statement.executeQuery(sql)){
            consumer.accept(resultSet);
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            logger.info("sql执行结束");
        }
    }

    /**
     * 执行不需要返回结果的sql
     */
    public static void execute(String uid,String sql){
        try (Connection connection = getConnection(uid);
             Statement statement = connection.createStatement();){
            statement.execute(sql);
        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            logger.info("sql执行结束");
        }
    }

    /**
     * @TODO 暂时只兼容mysql，其它的后续进行补充
     */
    private static String buildUrl(String ip, Integer port, String dbname) {
        String url = "jdbc:mysql://" + ip + ":" + port;
        if (StringUtils.isNotBlank(dbname)) url = url + "/" + dbname;
        url = url + "?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8";
        return url;
    }

}
